package sw6.visualschedule.persistence;

import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.SelectArg;

import sw6.visualschedule.entities.DbDate;
import sw6.visualschedule.entities.ScheduleActivity;

import android.content.Context;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class DateRepo extends AbstractDataRepo<DbDate> {
    
    private static final String LOG_NAME = "DateService";
    private transient Dao<ScheduleActivity, Integer> mActivityDao;
    
    /**
     * Initializes the repository.
     * @param base the context to run in.
     */
    public DateRepo(final Context base) {
        super(DbDate.class);
    
        this.attachBaseContext(base);

        try {
            mActivityDao = getHelper().getDao(ScheduleActivity.class);
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
    }
    
    /**
     * Returns a list of activities for a date.
     * Populates with instance dates and status.
     * @param date the date to filter by.
     * @return a list of activities.
     */
    public List<ScheduleActivity> getActivities(final Date date) {
        final List<ScheduleActivity> activities = new ArrayList<ScheduleActivity>();
        
        final Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(date);
        
        calendar.set(GregorianCalendar.HOUR_OF_DAY, 0);
        calendar.set(GregorianCalendar.MINUTE, 0);
        calendar.set(GregorianCalendar.SECOND, 0);
        final Date startDateRange = calendar.getTime();
        
        calendar.set(GregorianCalendar.HOUR_OF_DAY, 23);
        calendar.set(GregorianCalendar.MINUTE, 59);
        calendar.set(GregorianCalendar.SECOND, 59);
        final Date endDateRange = calendar.getTime();
        
        try {
            final QueryBuilder<DbDate, Integer> query = getDao().queryBuilder();
            
            final SelectArg dateClauseStart = new SelectArg();
            final SelectArg dateClauseEnd = new SelectArg();
            
            query.selectColumns(DbDate.ACTIVITY_ID_FIELD, DbDate.DATE_FIELD);
            query.where().between(DbDate.DATE_FIELD, dateClauseStart, dateClauseEnd);
            query.orderBy(DbDate.DATE_FIELD, true);
            
            final PreparedQuery<DbDate> preparedQuery = query.prepare();    
            
            dateClauseStart.setValue(startDateRange);
            dateClauseEnd.setValue(endDateRange);
            
            ScheduleActivity activity;
            for (DbDate dbDate : getDao().query(preparedQuery)) {
                activity = dbDate.getActivity();
                mActivityDao.refresh(activity);
                activity.setInstanceDate(dbDate.getDate());
                activities.add(activity);
            }
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
        
        return activities;
    }
    
    /**
     * Returns a list of dates for an activity.
     * @param activityId the activity id to filter by.
     * @return a list of dates.
     */
    public List<DbDate> getActivityDates(final int activityId) {
        List<DbDate> entries = null;
        
        try {
            final QueryBuilder<DbDate, Integer> query = getDao().queryBuilder();
            
            final SelectArg idClause = new SelectArg();
            query.where().eq(DbDate.ACTIVITY_ID_FIELD, idClause);
            query.orderBy(DbDate.DATE_FIELD, true);
            
            final PreparedQuery<DbDate> preparedQuery = query.prepare();
            
            idClause.setValue(activityId);
            
            entries = getDao().query(preparedQuery);
            
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
        
        return entries;
    }
}

